using System;
using System.IO;
using System.IO.Compression;
using System.Drawing;
using System.Net;
using System.Threading;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Windows.Forms;
using System.Xml;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Text.RegularExpressions;
using A = Acrobat;
using Tiffer;
using Dimok;
using DA = Dimok.Acrobat;

namespace FileHound {
	public class PDFHound : FileHound.BaseHound {

		private System.ComponentModel.Container components = null;

		Hound.Properties.Settings Settings;
		public PDFHound(Watcher watcher) {
			InitializeComponent();
			watcher.FileCreated += new FileCreatedDelegate(watcher_FileCreated);
			Settings = new Hound.Properties.Settings();
		}

		#region ======================== Windows Form Designer ========================
		private void InitializeComponent() {
			this.components = new System.ComponentModel.Container();
			this.Location = new Point(0, 0);
			this.StartPosition = FormStartPosition.Manual;
			this.Size = new System.Drawing.Size(400, 300);
			this.Text = "Image Hound";
		}
		protected override void Dispose(bool disposing) {
			if (disposing) {
				if (components != null) {
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}
		#endregion ====================================================================

		private void watcher_FileCreated(object sender, FileCreatedEventArgs e) {
			string ext = Settings.NoXml ? ".bc" : ".xml";
			if (e.Extention.ToLower() !=  ext) return;
			FileManager.WaitToLoad(e.FullName, 10 * 1000);
			AddToQue(new ProcessingFile(e.FullName, NumberOfRetries));
		}
		#region ======================== Application Recognition ======================
		//[MethodImplAttribute(MethodImplOptions.Synchronized)]
		public override bool ProcessFile(ProcessingFile file) {
			int ret = 0;
			string statusMessage = " returned from web service";
			string baseName = Regex.Replace(file.NameNoExt, "_00\\d\\d$", "", RegexOptions.RightToLeft);
			string pathOCR = file.Directory + "\\";
			string pathBarCode = pathOCR + baseName + ".bc";
			string pathXML = pathOCR + file.NameNoExt + ".xml";
			string pathTiff = pathOCR + baseName + ".tif";
			string pathPDF = pathOCR + baseName + ".pdf";
			
			if (!File.Exists(pathBarCode)) return false;
			Dimok.BarCode.DS.BarCodes dsBC = new Dimok.BarCode.DS.BarCodes();
			dsBC.ReadXml(pathBarCode);
			if (dsBC.BarCode.Select("TypeID=" + (int)Dimok.BarCodeTypes.BarCodingDone + "").Length == 0) return false;
			
			if (!File.Exists(pathTiff) && !File.Exists(pathPDF)) return false;
			if (File.Exists(pathTiff)) EnsurePDF(pathPDF, Tiff.PageCount(pathTiff));

			Hound.com.onrefund.Imaging wsImaging = new Hound.com.onrefund.Imaging();
			wsImaging.UseDefaultCredentials = true;
			string barCodeGUID = ((Dimok.BarCode.DS.BarCodes.BarCodeRow)dsBC.BarCode.Select("TypeID=" + (int)Dimok.BarCodeTypes.GUID + "")[0]).Code;
			if (wsImaging.ImageExists(barCodeGUID)) { ret = -1; statusMessage = " image exists."; }
			else {
				SetTotalFiles(file.RetryCount);
				Status = "Sending " + file.NameNoExt + " to database.";
				XmlDocument xmlDoc = new XmlDocument();
				if (File.Exists(pathXML)) {
					try {
						string xmlOCR = Regex.Replace(File.ReadAllText(pathXML),"&#\\d+;","");
						xmlDoc.LoadXml(Regex.Replace(Regex.Replace(xmlOCR, ">[\n\r]+", ">"), "[\x012\x011\x010]", ""));
						XmlNamespaceManager nsm = new XmlNamespaceManager(xmlDoc.NameTable);
						nsm.AddNamespace("ss", "http://www.scansoft.com/omnipage/xml/ssdoc-schema3.xsd");
						XmlNodeList pages = xmlDoc.SelectNodes("//ss:page", nsm);
						int p = 1;
						foreach (XmlElement page in pages)
							page.SetAttribute("number", (p++) + "");
					} catch {
						xmlDoc = new XmlDocument();
					}
				}
				wsImaging.Timeout = WebService.TimeOut * 60 * 1000;
				byte[] imagePDF = File.Exists(pathPDF) ? File.ReadAllBytes(pathPDF) : null;
				MemoryStream msPDF = new MemoryStream();
				if( imagePDF != null )
					new GZipStream(msPDF, CompressionMode.Compress).Write(imagePDF, 0, imagePDF.Length);
				string barCodeXml = File.Exists(pathBarCode) ? File.ReadAllText(pathBarCode) : null;
				MemoryStream msXml = new MemoryStream();
				if (xmlDoc != null)
					new GZipStream(msXml, CompressionMode.Compress).Write(Encoding.ASCII.GetBytes(xmlDoc.OuterXml), 0, xmlDoc.OuterXml.Length);
				ret = wsImaging.ImageToClaim(imagePDF, xmlDoc.OuterXml, barCodeXml);
			}
			/*if( ret == 0 )*/
			ErrorText = ret + statusMessage;
			//else
			if (!Common.DebugMode)
				foreach (string fileName in Directory.GetFiles(file.Directory, baseName + "*", SearchOption.AllDirectories))
					File.Delete(fileName);
			return true;
		}
		[MethodImplAttribute(MethodImplOptions.Synchronized)]
		private void EnsurePDF(string fileName, int pageCount) {
			if (CheckPageCount(fileName, pageCount)) return;
			A.CAcroAVDoc avDoc = null;
			try {
				avDoc = DA.CreateAVDocInstance(Path.ChangeExtension(fileName, "tif"));
				A.CAcroPDDoc pdDoc = (A.CAcroPDDoc)avDoc.GetPDDoc();
				pdDoc.Save((short)(A.PDSaveFlags.PDSaveFull | A.PDSaveFlags.PDSaveCollectGarbage | A.PDSaveFlags.PDSaveLinearized), fileName);
			} finally {
				try { avDoc.Close(1); Dimok.Common.DisposeThem(avDoc); } catch { }
			}

		}
		private bool CheckPageCount(string fileName, int pageCount) {
			if (!File.Exists(fileName)) return false;
			A.CAcroAVDoc avDoc = null;
			try {
				avDoc = DA.CreateAVDocInstance(fileName);
				A.CAcroPDDoc pdDoc = (A.CAcroPDDoc)avDoc.GetPDDoc();
				return pdDoc.GetNumPages() == pageCount;
			} finally {
				try { avDoc.Close(1); Dimok.Common.DisposeThem(avDoc); } catch { }
			}

		}
		#endregion ====================================================================

	}
}